import gradio as gr
import os
import shutil

from dotenv import load_dotenv
from zhipuai import ZhipuAI

load_dotenv()
api_key = os.getenv("api_key_zp")
client = ZhipuAI(api_key=api_key)
# css页面
css = """
#file_upload {
    height:400px
}
"""
# 定义一个变量,默认为False
inter = False

# 文件上传校验
file_type = [".txt"]

# 文件上传的存储目录
dir_path = "./data"


# 点击单选,选择普通聊天或者文本处理
def assistant_fn():
    """
        功能分析:
            当我们点击普通聊天的时候
                标题显示普通聊天
                选择助手和上传文件需要禁用
            当我们点击文本处理的时候
                标题就显示文本处理
                选择助手和上传文件需要阔以使用
        实现步骤:
            1. 定义一个变量,当普通聊天,变量为False,表示不能上传文件和选择助手,为True可以
    """
    global inter  # 全局变量
    inter = not inter  # True => False , F => T
    print(inter)
    if inter:
        type = "文本处理"
    else:
        type = "普通聊天"
    return [
        gr.HTML(f"<h1 align='center'>{type}</h1>"),
        gr.Dropdown(
            label="请选择一个文本助手",
            choices=["文本分类", "文本抽取", "文本匹配"],
            interactive=inter
        ),
        gr.File(
            label="请上传文件",
            elem_id="file_upload",
            interactive=inter
        ),
        gr.Textbox(
            label="输入",
            placeholder="请输入你要查询的内容",
            interactive=not inter
        ),
        gr.Button("提交", interactive=not inter)
    ]


# 定义一个变量,用户存储历史消息
message_history = []


# 普通消息的发送
def submit_fn(val):
    if len(val.strip()) == 0:
        return ["", []]
    global message_history
    """
        1. 接受val,val就是用户输入的内容
        2. 将用户输入的内容组装成一个prompt
        3. 将prompt发送给AI大模型
        4. 将模型返回的结果交给chatbot去了
    """
    instruction = """请说中文"""
    prompt = f"""
        {instruction}
        {val}
    """
    # print(prompt)
    response = chat_function(prompt)
    # 将组成成好问题与答案组成一个列表,让后添加到那个message_history这个大的列表当中来
    message_history.append([val, response])
    # print("历史消息")
    # print(message_history)
    # print(len(message_history))
    # print("历史消息")
    message_history = message_history[-3:]
    return ["", message_history]  # 前面这个交给的是用户输入,后面这个交给的聊天界面


instruction = """
    你是一个文本效果处理专家，你的工作对于我给定的文本进行文本分类。
"""
example = """
    "本季流行趋势中，撞色拼接和复古风格大行其道，我们的新款服装系列融合了这些元素，为追求时尚的你带来独一无二的穿着体验。" 属于[服装,水果,家电,玩具]中的哪一类?  答案: 服装
    “阳光果园直供，我们的新鲜草莓色泽红润、果实饱满，每一颗都是精心挑选，确保您品尝到最纯净的自然甜味。这属于[服装, 水果, 家电, 玩具, 水果]中的哪一类?” 答案: 水果
"""
user_input = """
    使用就是我们作为文件上传的内容
"""
out_put = """
    属于：[服装, 水果, 家电, 玩具, 水果]类别中。
"""


# 文本处理的下拉框的切换
def test_type_fn(val):
    global instruction
    global example
    global user_input
    global out_put
    # print(val)
    if val == "文本剥离":
        instruction = """
            你是一个文本效果处理专家，你的工作对于我给定的文本进行文本提取。
            """
        example = """
            在8月17日至8月23日，王老师将引导学生深入探讨大学心理学导论，课程内容将涵盖心理分析，旨在帮助学生理解人类行为背后的心理机制 
            提取内容"课程名称": "大学心理学导论","授课老师": "王老师","上课时间": "8月17日至8月23日","课程内容": "心理分析，人类行为背后的心理机制","课程目标": "帮助学生深入理解心理学导论，探索人类行为背后的心理机制"
            """
        user_input = """
            使用就是我们作为文件上传的内容
            """
        out_put = """
            以JSON的格式返回
            """
    elif val == "文本分类":
        instruction = """
           你是一个文本效果处理专家，你的工作对于我给定的文本进行文本分类。
           """
        example = """
           "本季流行趋势中，撞色拼接和复古风格大行其道，我们的新款服装系列融合了这些元素，为追求时尚的你带来独一无二的穿着体验。" 属于[服装,水果,家电,玩具]中的哪一类? 答案: 服装
    “阳光果园直供，我们的新鲜草莓色泽红润、果实饱满，每一颗都是精心挑选，确保您品尝到最纯净的自然甜味。这属于[服装, 水果, 家电, 玩具, 水果]中的哪一类?” 答案: 水果
           """
        user_input = "他里面的内容就是你作为文件上传的内容"
        out_put = """
           属于：[服装, 水果, 家电, 玩具]类别中。
           """
    elif val == "文本匹配":
        instruction = """
        你是一个文本效果处理专家，你的工作对于我给定的文本进行文本匹配。
        """
        example = """
            “随着社区绿化项目的完成，居民们享受到了更加清新宜人的生活环境，户外活动也因此变得更加愉快。” 结果:正面,
            “本地超市推出了一系列健康有机食品，满足了消费者对高品质生活的追求，让健康饮食变得更加便捷。” 结果:正面,
            “智能家居设备的普及让家庭生活更加便捷舒适，提高了居民的生活质量，引领了现代居家新潮流。” 结果:正面,
            “城市交通拥堵问题日益严重，给居民的日常出行带来了极大不便，影响了生活质量。” 结果:负面,
			“生活成本不断上升，特别是食品和住房费用增加，让许多家庭感受到了经济压力。” 结果:负面,
			“环境污染问题持续加剧，空气质量下降，居民的健康和生活舒适度受到了直接影响。” 结果:负面,
        """
        user_input = """
        使用就是我们作为文件上传内容
        """
        out_put = """
        请告诉我是正面还是负面即可
        ['正面','负面']
        """


# 存储消息
history_msg = []


# 文件上传的事件
def file_upload_fn(filename):
    """
    1. 文件存储
    2. 文件读取
    3. 交给大模型
    """
    # 获取文件上传的名字
    basename = os.path.basename(filename)
    # print(basename)
    # 获取文件上传的后缀名
    suff = os.path.splitext(basename)[-1]
    # print(suff)
    # 文件上传校验
    if suff in file_type:
        # 如果文件夹存在,那么就忽略,如果不存在,那么就创建
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)
        # 将我们上传的内容存储到文件夹里面去
        # 移动文件到指定目录
        shutil.move(filename, dir_path)
        # 获取存储的文件
        file_name = os.path.join(dir_path, basename)
        # 如何文件夹存在,那么就保存,如果文件夹没有存在,那么就忽略
        with open(file_name, 'r', encoding='utf-8') as file:
            content = file.read()
            res = content.split("\n\n")
            for i in range(0, len(res), 3):
                # print("user_input")
                # print(res[i:i + 3])
                # print("instruction")
                # print(instruction)
                # print("example")
                # print(example)
                # print("out_put")
                # print(out_put)
                prompt = f"""
                {instruction}
                请学习
                {example}
                请回答
                {res[i:i + 3]}
                {out_put}
                """
                print(prompt)
                print("模型的终极回复")
                message = [
                    {
                        "role": "user",
                        "content": prompt
                    }
                ]
                response = client.chat.completions.create(
                    model="glm-4-plus",  # 填写需要调用的模型编码
                    messages=message,
                )
                # response.choices[0].message.content
                history_msg.append(
                    [prompt, response.choices[0].message.content]
                )
        return history_msg
    else:
        # 不允许上传
        print("不允许上传")
        pass


def chat_function(prompt, model="glm-4-plus"):
    print("prompt")
    print(prompt)
    print("prompt")
    message = [
        {
            "role": "user",
            "content": prompt
        }
    ]
    response = client.chat.completions.create(
        model=model,  # 填写需要调用的模型编码
        messages=message,
    )
    return response.choices[0].message.content


# 创建Gradio Blocks应用
with gr.Blocks(css=css) as demo:
    # 页面标题
    title = gr.HTML("<h1 align='center'>普通聊天</h1>")
    # 一行
    with gr.Row():
        # 列 => 单选框
        with gr.Column(scale=5):
            assistant = gr.Radio(
                label="请选择助手",
                choices=["普通聊天", "文本处理"],
                value="普通聊天",
                interactive=True
            )
        # 列 => 下拉框
        with gr.Column(scale=1):
            text_type = gr.Dropdown(
                label="请选择一个文本助手",
                choices=["文本分类", "文本剥离", "文本匹配"],
                interactive=False
            )
    # 一行
    with gr.Row():
        # 列 => 聊天
        with gr.Column(scale=5):
            chat_bot = gr.Chatbot(
                show_label=False,  # 取消标签
                show_copy_button=True,  # 允许复制
            )
        # 列表
        with gr.Column(scale=1):
            file_upload = gr.File(
                label="请上传文件",
                elem_id="file_upload",
                interactive=False
            )
    # 一行
    user_input_ = gr.Textbox(
        label="输入",
        placeholder="请输入你要查询的内容",
        interactive=True
    )
    # 提交按钮
    submit_btn = gr.Button("提交", interactive=True)
    # 点击助手切换
    assistant.change(fn=assistant_fn, inputs=None, outputs=[title, text_type, file_upload, user_input_, submit_btn])
    # 按回车
    user_input_.submit(fn=submit_fn, inputs=user_input_, outputs=[user_input_, chat_bot])
    submit_btn.click(fn=submit_fn, inputs=user_input_, outputs=[user_input_, chat_bot])
    # 文本分类的下拉框切换
    text_type.change(fn=test_type_fn, inputs=[text_type], outputs=None)
    # 文件上传的事件
    file_upload.change(fn=file_upload_fn, inputs=file_upload, outputs=[chat_bot])

if __name__ == '__main__':
    # 运行
    demo.launch()
